	LIST   P=PIC16F877a
	#INCLUDE "P16F877A.INC"
	;errorlevel -302		;suppress "not in bank 0" message

	__CONFIG        _CP_OFF & _DEBUG_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _HS_OSC

; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.

;Memory definition:
Ram		EQU	h'20'		; Look datasheets gpr starts at file address 20h
WREG_TEMP	EQU	Ram+0		;storage for WREG during interrupt
STATUS_TEMP	EQU	Ram+1		;storage for STATUS during interrupt
PCLATH_TEMP	EQU	Ram+2		;storage for PCLATH during interrupt
FSR_TEMP	EQU	Ram+3		;storage for FSR during interrupt	
Timer_local	EQU	Ram+10
DataIN1		EQU	Ram+11
DataIN2		EQU	Ram+12
DutyCycle	EQU	Ram+13


		ORG     0x0000		;Reset vector
 		GOTO	Main
		nop
		nop		
		ORG	0x0004		;Interrupt vector
		GOTO 	Int

Main		
		Bank0
		CALL	SetupSerial
		CLRF	PORTD		;All of portd low
		MOVLW	B'00000000'
		MOVWF	ADCON0
		Bank1
		CLRF	TRISD	
		MOVLW	B'00000110'
		MOVWF	ADCON1
		MOVLW	0x07
		MOVWF	CMCON	
		Bank0	

Loop		
		BTFSS	PIR1,TXIF	;Check if transmitter busy	
		GOTO	Loop1ms
		GOTO	Loop	

SetupSerial
		Bank1			;Select bank 1
		BCF	TRISC,6		;Make RC6 - TX pin an output
		BSF	TRISC,7		;Make RC7 - RX pin an input
		BCF	TXSTA,BRGH	;Select low speed mode	
		MOVLW	D'12'
		MOVWF	SPBRG		;Select baud rate 9600 in low speed	
		BCF	TXSTA,SYNC	;Select async mode	
		BSF	TXSTA,TXEN	;Enable Transmit
		Bank0			;Select bank0
		movlw	0x90		;Enable serial port and reception
		movwf	RCSTA
		movlw	0xc0		;Enable global and peripheral ints
		movwf	INTCON
		Bank1			;Select bank1
		movlw	0x20		;(0x30 enable TX) and RX interrupts
		movwf	PIE1
		Bank0
		return

SetupPWM
		BSF	STATUS,RP0	; reg. Bank 0 (kijk blz 68 van datasheet voor meer informatie)
		MOVLW	H'ff'		; 11111111
		MOVWF	PR2		
		BCF	STATUS,RP0	; reg. Bank 0
		MOVLW	D'0'
		MOVWF	CCPR1L		; Set Duty Cycle to 0		
		MOVLW	B'00000100'
		MOVLW	D'0'
		MOVWF	CCPR2L		; Set Duty Cycle to 0		
		MOVLW	B'00000100'
		MOVWF	T2CON	
		MOVLW	B'00111100'
		MOVWF	CCP1CON	
		MOVWF	CCP2CON
		RETURN 

Loop1ms
		ADDLW	d'255'		;Dec W
		BTFSS	STATUS, Z	;Zero flag set?
		GOTO 	Loop1ms		;	No, keep looping
		RETURN			;	Yes, 1ms done

Int
		movwf	WREG_TEMP	;Save WREG
		movf	STATUS,W	;Store STATUS in WREG
		clrf	STATUS		;Select file register bank0
		movwf	STATUS_TEMP	;Save STATUS value
		movf	PCLATH,W	;Store PCLATH in WREG
		movwf	PCLATH_TEMP	;Save PCLATH value
		clrf	PCLATH		;Select program memory page0
		movf	FSR,W		;Store FSR in WREG
		movwf	FSR_TEMP	;Save FSR value

		Bank0			;Select bank0
		btfsc	PIR1,RCIF	;Test RCIF receive interrupt
		bsf	STATUS,RP0	;Change to bank1 if RCIF set
		btfsc	PIE1,RCIE	;Test if interrupt enabled if RCIF set
		goto	GetData		;If RCIF and RCIE set, do receive

		Bank0			;Select bank0
		btfsc	PIR1,TXIF	;Test for TXIF transmit interrupt
		bsf	STATUS,RP0	;Change to bank1 if TXIF set
		btfsc	PIE1,TXIE	;Test if interrupt enabled if TXIF set
		goto	EndInt		;If TXIF and TCIE set, do transmit

;can do special error handling here - an unexpected interrupt occurred 
EndInt
		Bank0			;Select bank 0
		movf	FSR_TEMP,W	;Get saved FSR value
		movwf	FSR		;Restore FSR
		movf	PCLATH_TEMP,W	;Get saved PCLATH value
		movwf	PCLATH		;Restore PCLATH
		movf	STATUS_TEMP,W	;Get saved STATUS value
		movwf	STATUS		;Restore STATUS
		swapf	WREG_TEMP,F	;Prepare WREG to be restored
		swapf	WREG_TEMP,W	;Restore WREG without affecting STATUS
		retfie			;Return from interrupt

;Get received data 
GetData	
		Bank0
		btfsc	RCSTA,OERR	;Test overrun error flag
		goto	ErrOERR		;Handle it if error
		btfsc	RCSTA,FERR	;Test framing error flag
		goto	ErrFERR		;Handle it if error

		movf	DataIN1,W	;Move last received data		
		movwf	DataIN2

		movf	RCREG,W		;Get received data
		movwf	DataIN1		;Copy to DataIn1

		SUBLW	D'0'
		BTFSS	STATUS,Z	;Test if last data was 0
		GOTO	BlockNotComplete

;SetDutyCycle	
		movf	DataIN2,W	;Move last received data		
		movwf	DutyCycle

;VisualOutputs	
		MOVF	DataIN2,W	
		ANDWF	B'11111111'
		MOVWF	PORTD
		
BlockNotComplete
		goto	EndInt
;error because OERR overrun error bit is set - clear and continue
ErrOERR
		bcf	RCSTA,CREN	;reset the receiver logic
		bsf	RCSTA,CREN	;enable reception again
		goto	EndInt
;error because FERR framing error bit is set - clear and continue
ErrFERR	
		movf	RCREG,W		;discard received data that has error
		goto	EndInt


		GOTO	EndInt



		END			; End source code
					; Kristof Goris

		